package com.wx_shop.api.security;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.core.session.SessionRegistryImpl;

import com.wx_shop.api.mapper.SysAuthorityMapper;

/**
 * RBAC控制 <br>
 * 权限加载 用户的角色改变或角色的权限改变都需在更新所有登录用户的权限
 */
@Configuration
public class ApplicationSecurity extends WebSecurityConfigurerAdapter {

	private static Logger logger = LoggerFactory.getLogger(ApplicationSecurity.class);

	@Resource
	private MyUserDetailsService myUserDetailsService;

	@Autowired
	private SysAuthorityMapper sysAuthorityMapper;

	private SessionRegistry sessionRegistry;

	@Bean
	protected SessionRegistry getSessionRegistry() {
		this.sessionRegistry = new SessionRegistryImpl();
		return sessionRegistry;
	}

	@Override
	public void configure(WebSecurity web) throws Exception {
		web.ignoring().antMatchers(
				"/css/**", 
				"/js/**", 
				"/images/**", 
				"/api/user/miniProgramLogin"
			);
	}

	@Override
	protected void configure(HttpSecurity http) throws Exception {

		logger.info("configure...");
		
		http.headers().frameOptions().disable();
		http.csrf().disable();
		
		http.authorizeRequests().anyRequest().authenticated();
		
		http.addFilter(new JWTAuthenticationFilter(authenticationManager())); // JWT 认证
		http.exceptionHandling().accessDeniedHandler(new MyAccessDeniedHandler()); // 无权限
		http.exceptionHandling().authenticationEntryPoint(new MyAuthenticationEntryPoint()); // 未登录
		
		// 一个账号只充许一个同时在线
		http.sessionManagement().maximumSessions(1).sessionRegistry(sessionRegistry);

	}

	@Override
	public void configure(AuthenticationManagerBuilder auth) throws Exception {
		auth.userDetailsService(myUserDetailsService).passwordEncoder(new MyMd5PasswordEncoder());
	}
}